import fs from 'fs/promises'
import crypto from 'crypto'
import { prisma } from '@/lib/database'
import { NotFoundError } from '@/middleware/errorHandler'

export interface SecurityScanResult {
  scanId: string
  versionId: string
  scanType: 'vulnerability' | 'malware' | 'dependency' | 'code_quality' | 'license'
  status: 'pending' | 'running' | 'completed' | 'failed'
  result: 'pass' | 'warning' | 'fail'
  score: number // 0-100
  findings: SecurityFinding[]
  metadata: Record<string, any>
  startedAt: Date
  completedAt?: Date
}

export interface SecurityFinding {
  id: string
  type: 'vulnerability' | 'malware' | 'suspicious_code' | 'dependency_issue' | 'license_issue'
  severity: 'low' | 'medium' | 'high' | 'critical'
  title: string
  description: string
  file?: string
  line?: number
  column?: number
  cve?: string
  cwe?: string
  recommendation: string
  references: string[]
}

export interface ThreatIntelligence {
  source: string
  type: 'malware_hash' | 'suspicious_domain' | 'known_vulnerability' | 'malicious_pattern'
  indicator: string
  severity: 'low' | 'medium' | 'high' | 'critical'
  description: string
  lastUpdated: Date
}

export interface SecurityPolicy {
  id: string
  name: string
  description: string
  rules: SecurityRule[]
  enabled: boolean
  createdAt: Date
  updatedAt: Date
}

export interface SecurityRule {
  id: string
  type: 'file_pattern' | 'code_pattern' | 'dependency_check' | 'size_limit' | 'permission_check'
  pattern: string
  action: 'allow' | 'warn' | 'block'
  severity: 'low' | 'medium' | 'high' | 'critical'
  message: string
}

export class AdvancedSecurityService {
  private readonly maxFileSize = 100 * 1024 * 1024 // 100MB
  private readonly suspiciousPatterns = [
    /eval\s*\(/gi,
    /Function\s*\(/gi,
    /document\.write/gi,
    /innerHTML\s*=/gi,
    /outerHTML\s*=/gi,
    /\.exec\s*\(/gi,
    /child_process/gi,
    /fs\.writeFile/gi,
    /require\s*\(\s*['"`]child_process['"`]\s*\)/gi,
    /require\s*\(\s*['"`]fs['"`]\s*\)/gi,
    /XMLHttpRequest/gi,
    /fetch\s*\(/gi,
    /window\.location/gi,
    /document\.location/gi,
    /localStorage/gi,
    /sessionStorage/gi,
    /indexedDB/gi,
    /webkitRequestFileSystem/gi,
    /navigator\.geolocation/gi,
    /navigator\.camera/gi,
    /navigator\.microphone/gi
  ]

  // 执行完整安全扫描
  async performComprehensiveScan(versionId: string): Promise<SecurityScanResult[]> {
    const version = await prisma.pluginVersion.findUnique({
      where: { id: versionId },
      include: {
        plugin: {
          include: {
            developer: true
          }
        }
      }
    })

    if (!version) {
      throw new NotFoundError('Plugin version not found')
    }

    const scanResults: SecurityScanResult[] = []

    // 1. 恶意软件扫描
    const malwareScan = await this.scanForMalware(versionId, version.filePath)
    scanResults.push(malwareScan)

    // 2. 漏洞扫描
    const vulnerabilityScan = await this.scanForVulnerabilities(versionId, version.filePath)
    scanResults.push(vulnerabilityScan)

    // 3. 依赖项安全扫描
    const dependencyScan = await this.scanDependencies(versionId, version.filePath)
    scanResults.push(dependencyScan)

    // 4. 代码质量扫描
    const codeQualityScan = await this.scanCodeQuality(versionId, version.filePath)
    scanResults.push(codeQualityScan)

    // 5. 许可证合规扫描
    const licenseScan = await this.scanLicenseCompliance(versionId, version.filePath)
    scanResults.push(licenseScan)

    // 保存扫描结果到数据库
    for (const result of scanResults) {
      await this.saveScanResult(result)
    }

    return scanResults
  }

  // 恶意软件扫描
  private async scanForMalware(versionId: string, filePath: string): Promise<SecurityScanResult> {
    const scanId = crypto.randomUUID()
    const startedAt = new Date()
    const findings: SecurityFinding[] = []

    try {
      // 检查文件大小
      const stats = await fs.stat(filePath)
      if (stats.size > this.maxFileSize) {
        findings.push({
          id: crypto.randomUUID(),
          type: 'malware',
          severity: 'high',
          title: 'Suspicious File Size',
          description: `File size (${stats.size} bytes) exceeds normal plugin size limits`,
          recommendation: 'Review file contents for unnecessary large files or potential data exfiltration',
          references: []
        })
      }

      // 计算文件哈希
      const fileBuffer = await fs.readFile(filePath)
      const fileHash = crypto.createHash('sha256').update(fileBuffer).digest('hex')

      // 检查已知恶意软件哈希
      const knownMalware = await this.checkThreatIntelligence('malware_hash', fileHash)
      if (knownMalware) {
        findings.push({
          id: crypto.randomUUID(),
          type: 'malware',
          severity: 'critical',
          title: 'Known Malware Detected',
          description: `File matches known malware signature: ${knownMalware.description}`,
          recommendation: 'Immediately reject this plugin and investigate the developer',
          references: []
        })
      }

      // 扫描可疑代码模式
      const fileContent = fileBuffer.toString('utf8')
      await this.scanForSuspiciousPatterns(fileContent, findings)

      const score = this.calculateSecurityScore(findings)
      const result = this.determineResult(findings)

      return {
        scanId,
        versionId,
        scanType: 'malware',
        status: 'completed',
        result,
        score,
        findings,
        metadata: {
          fileSize: stats.size,
          fileHash,
          patternsChecked: this.suspiciousPatterns.length
        },
        startedAt,
        completedAt: new Date()
      }

    } catch (error) {
      return {
        scanId,
        versionId,
        scanType: 'malware',
        status: 'failed',
        result: 'fail',
        score: 0,
        findings: [{
          id: crypto.randomUUID(),
          type: 'malware',
          severity: 'high',
          title: 'Scan Failed',
          description: `Malware scan failed: ${error instanceof Error ? error.message : 'Unknown error'}`,
          recommendation: 'Manual review required',
          references: []
        }],
        metadata: { error: error instanceof Error ? error.message : 'Unknown error' },
        startedAt,
        completedAt: new Date()
      }
    }
  }

  // 漏洞扫描
  private async scanForVulnerabilities(versionId: string, filePath: string): Promise<SecurityScanResult> {
    const scanId = crypto.randomUUID()
    const startedAt = new Date()
    const findings: SecurityFinding[] = []

    try {
      const fileBuffer = await fs.readFile(filePath)
      const fileContent = fileBuffer.toString('utf8')

      // 检查常见的安全漏洞模式
      const vulnerabilityPatterns = [
        {
          pattern: /document\.write\s*\(/gi,
          cwe: 'CWE-79',
          title: 'Potential XSS Vulnerability',
          description: 'Use of document.write() can lead to XSS attacks',
          severity: 'medium' as const
        },
        {
          pattern: /innerHTML\s*=\s*[^;]+\+/gi,
          cwe: 'CWE-79',
          title: 'Potential XSS via innerHTML',
          description: 'Dynamic content assignment to innerHTML without sanitization',
          severity: 'high' as const
        },
        {
          pattern: /eval\s*\(/gi,
          cwe: 'CWE-95',
          title: 'Code Injection Risk',
          description: 'Use of eval() can lead to code injection vulnerabilities',
          severity: 'critical' as const
        },
        {
          pattern: /new\s+Function\s*\(/gi,
          cwe: 'CWE-95',
          title: 'Dynamic Code Execution',
          description: 'Dynamic function creation can be exploited for code injection',
          severity: 'high' as const
        }
      ]

      for (const vuln of vulnerabilityPatterns) {
        const matches = fileContent.matchAll(vuln.pattern)
        for (const _ of matches) {
          findings.push({
            id: crypto.randomUUID(),
            type: 'vulnerability',
            severity: vuln.severity,
            title: vuln.title,
            description: vuln.description,
            cwe: vuln.cwe,
            recommendation: 'Review and sanitize user input, use safe alternatives',
            references: [`https://cwe.mitre.org/data/definitions/${vuln.cwe.split('-')[1]}.html`]
          })
        }
      }

      const score = this.calculateSecurityScore(findings)
      const result = this.determineResult(findings)

      return {
        scanId,
        versionId,
        scanType: 'vulnerability',
        status: 'completed',
        result,
        score,
        findings,
        metadata: {
          patternsChecked: vulnerabilityPatterns.length,
          totalMatches: findings.length
        },
        startedAt,
        completedAt: new Date()
      }

    } catch (error) {
      return {
        scanId,
        versionId,
        scanType: 'vulnerability',
        status: 'failed',
        result: 'fail',
        score: 0,
        findings: [{
          id: crypto.randomUUID(),
          type: 'vulnerability',
          severity: 'high',
          title: 'Scan Failed',
          description: `Vulnerability scan failed: ${error instanceof Error ? error.message : 'Unknown error'}`,
          recommendation: 'Manual review required',
          references: []
        }],
        metadata: { error: error instanceof Error ? error.message : 'Unknown error' },
        startedAt,
        completedAt: new Date()
      }
    }
  }

  // 依赖项安全扫描
  private async scanDependencies(versionId: string, filePath: string): Promise<SecurityScanResult> {
    const scanId = crypto.randomUUID()
    const startedAt = new Date()
    const findings: SecurityFinding[] = []

    try {
      // 这里可以集成真实的依赖项扫描工具，如 npm audit, snyk 等
      // 目前实现一个基础版本

      const fileBuffer = await fs.readFile(filePath)
      const fileContent = fileBuffer.toString('utf8')

      // 检查是否有 package.json
      if (fileContent.includes('package.json') || fileContent.includes('"dependencies"')) {
        // 模拟依赖项检查
        const suspiciousDependencies = [
          'eval-package',
          'malicious-lib',
          'crypto-miner',
          'data-stealer'
        ]

        for (const dep of suspiciousDependencies) {
          if (fileContent.includes(dep)) {
            findings.push({
              id: crypto.randomUUID(),
              type: 'dependency_issue',
              severity: 'critical',
              title: 'Suspicious Dependency Detected',
              description: `Potentially malicious dependency found: ${dep}`,
              recommendation: 'Remove suspicious dependency and use trusted alternatives',
              references: []
            })
          }
        }
      }

      const score = this.calculateSecurityScore(findings)
      const result = this.determineResult(findings)

      return {
        scanId,
        versionId,
        scanType: 'dependency',
        status: 'completed',
        result,
        score,
        findings,
        metadata: {
          dependenciesChecked: true,
          suspiciousFound: findings.length
        },
        startedAt,
        completedAt: new Date()
      }

    } catch (error) {
      return {
        scanId,
        versionId,
        scanType: 'dependency',
        status: 'failed',
        result: 'fail',
        score: 0,
        findings: [],
        metadata: { error: error instanceof Error ? error.message : 'Unknown error' },
        startedAt,
        completedAt: new Date()
      }
    }
  }

  // 代码质量扫描
  private async scanCodeQuality(versionId: string, filePath: string): Promise<SecurityScanResult> {
    const scanId = crypto.randomUUID()
    const startedAt = new Date()
    const findings: SecurityFinding[] = []

    try {
      const fileBuffer = await fs.readFile(filePath)
      const fileContent = fileBuffer.toString('utf8')

      // 检查代码质量问题
      const qualityChecks = [
        {
          pattern: /console\.log/gi,
          title: 'Debug Code Found',
          description: 'Console.log statements found in production code',
          severity: 'low' as const
        },
        {
          pattern: /debugger;/gi,
          title: 'Debugger Statement',
          description: 'Debugger statements should not be in production code',
          severity: 'medium' as const
        },
        {
          pattern: /TODO|FIXME|HACK/gi,
          title: 'Incomplete Code',
          description: 'Code contains TODO/FIXME/HACK comments indicating incomplete implementation',
          severity: 'low' as const
        }
      ]

      for (const check of qualityChecks) {
        const matches = fileContent.matchAll(check.pattern)
        for (const _ of matches) {
          findings.push({
            id: crypto.randomUUID(),
            type: 'code_quality' as any,
            severity: check.severity,
            title: check.title,
            description: check.description,
            recommendation: 'Clean up code before production release',
            references: []
          })
        }
      }

      const score = this.calculateSecurityScore(findings)
      const result = this.determineResult(findings)

      return {
        scanId,
        versionId,
        scanType: 'code_quality',
        status: 'completed',
        result,
        score,
        findings,
        metadata: {
          checksPerformed: qualityChecks.length,
          issuesFound: findings.length
        },
        startedAt,
        completedAt: new Date()
      }

    } catch (error) {
      return {
        scanId,
        versionId,
        scanType: 'code_quality',
        status: 'failed',
        result: 'fail',
        score: 0,
        findings: [],
        metadata: { error: error instanceof Error ? error.message : 'Unknown error' },
        startedAt,
        completedAt: new Date()
      }
    }
  }

  // 许可证合规扫描
  private async scanLicenseCompliance(versionId: string, filePath: string): Promise<SecurityScanResult> {
    const scanId = crypto.randomUUID()
    const startedAt = new Date()
    const findings: SecurityFinding[] = []

    try {
      const fileBuffer = await fs.readFile(filePath)
      const fileContent = fileBuffer.toString('utf8')

      // 检查许可证相关问题
      const licensePatterns = [
        'GPL-3.0',
        'AGPL',
        'SSPL',
        'Commons Clause'
      ]

      for (const license of licensePatterns) {
        if (fileContent.includes(license)) {
          findings.push({
            id: crypto.randomUUID(),
            type: 'license_issue',
            severity: 'medium',
            title: 'Restrictive License Detected',
            description: `Code contains references to restrictive license: ${license}`,
            recommendation: 'Review license compatibility with platform terms',
            references: []
          })
        }
      }

      const score = this.calculateSecurityScore(findings)
      const result = this.determineResult(findings)

      return {
        scanId,
        versionId,
        scanType: 'license',
        status: 'completed',
        result,
        score,
        findings,
        metadata: {
          licensesChecked: licensePatterns.length,
          issuesFound: findings.length
        },
        startedAt,
        completedAt: new Date()
      }

    } catch (error) {
      return {
        scanId,
        versionId,
        scanType: 'license',
        status: 'failed',
        result: 'fail',
        score: 0,
        findings: [],
        metadata: { error: error instanceof Error ? error.message : 'Unknown error' },
        startedAt,
        completedAt: new Date()
      }
    }
  }

  // 扫描可疑代码模式
  private async scanForSuspiciousPatterns(content: string, findings: SecurityFinding[]): Promise<void> {
    for (const pattern of this.suspiciousPatterns) {
      const matches = content.matchAll(pattern)
      for (const match of matches) {
        findings.push({
          id: crypto.randomUUID(),
          type: 'suspicious_code',
          severity: 'medium',
          title: 'Suspicious Code Pattern',
          description: `Potentially dangerous code pattern detected: ${match[0]}`,
          recommendation: 'Review code for security implications',
          references: []
        })
      }
    }
  }

  // 检查威胁情报
  private async checkThreatIntelligence(type: string, indicator: string): Promise<ThreatIntelligence | null> {
    // 这里可以集成真实的威胁情报源
    // 目前返回模拟数据
    const knownThreats = [
      'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', // empty file hash
      'malicious-domain.com',
      'evil-script.js'
    ]

    if (knownThreats.includes(indicator)) {
      return {
        source: 'Internal Threat DB',
        type: type as any,
        indicator,
        severity: 'critical',
        description: 'Known malicious indicator',
        lastUpdated: new Date()
      }
    }

    return null
  }

  // 计算安全评分
  private calculateSecurityScore(findings: SecurityFinding[]): number {
    if (findings.length === 0) return 100

    let totalDeduction = 0
    for (const finding of findings) {
      switch (finding.severity) {
        case 'critical':
          totalDeduction += 40
          break
        case 'high':
          totalDeduction += 25
          break
        case 'medium':
          totalDeduction += 15
          break
        case 'low':
          totalDeduction += 5
          break
      }
    }

    return Math.max(0, 100 - totalDeduction)
  }

  // 确定扫描结果
  private determineResult(findings: SecurityFinding[]): 'pass' | 'warning' | 'fail' {
    const criticalFindings = findings.filter(f => f.severity === 'critical')
    const highFindings = findings.filter(f => f.severity === 'high')

    if (criticalFindings.length > 0) return 'fail'
    if (highFindings.length > 2) return 'fail'
    if (findings.length > 5) return 'warning'
    if (findings.length > 0) return 'warning'

    return 'pass'
  }

  // 保存扫描结果
  private async saveScanResult(result: SecurityScanResult): Promise<void> {
    await prisma.securityScan.create({
      data: {
        id: result.scanId,
        versionId: result.versionId,
        scanType: result.scanType,
        status: result.status,
        result: result.result,
        findings: JSON.stringify(result.findings),
        // metadata: JSON.stringify(result.metadata), // 暂时注释，数据库模型中没有此字段
        startedAt: result.startedAt,
        completedAt: result.completedAt
      }
    })
  }

  // 获取扫描历史
  async getScanHistory(versionId: string): Promise<SecurityScanResult[]> {
    const scans = await prisma.securityScan.findMany({
      where: { versionId },
      orderBy: { startedAt: 'desc' }
    })

    return scans.map(scan => ({
      scanId: scan.id,
      versionId: scan.versionId,
      scanType: scan.scanType as any,
      status: scan.status as any,
      result: scan.result as any,
      score: scan.score || 0,
      findings: JSON.parse(scan.findings as string || '[]'),
      metadata: {}, // 暂时返回空对象，数据库模型中没有此字段
      startedAt: scan.startedAt || new Date(),
      completedAt: scan.completedAt || undefined
    }))
  }

  // 获取安全统计
  async getSecurityStats(): Promise<any> {
    const [
      totalScans,
      passedScans,
      warningScans,
      failedScans,
      criticalFindings,
      recentScans
    ] = await Promise.all([
      prisma.securityScan.count(),
      prisma.securityScan.count({ where: { result: 'pass' } }),
      prisma.securityScan.count({ where: { result: 'warning' } }),
      prisma.securityScan.count({ where: { result: 'fail' } }),
      prisma.securityScan.count({
        where: {
          findings: {
            string_contains: '"severity":"critical"'
          }
        }
      }),
      prisma.securityScan.count({
        where: {
          startedAt: {
            gte: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000) // 最近7天
          }
        }
      })
    ])

    return {
      totalScans,
      passedScans,
      warningScans,
      failedScans,
      criticalFindings,
      recentScans,
      passRate: totalScans > 0 ? Math.round((passedScans / totalScans) * 100) : 0
    }
  }

  // 创建安全策略
  async createSecurityPolicy(policy: Omit<SecurityPolicy, 'id' | 'createdAt' | 'updatedAt'>): Promise<SecurityPolicy> {
    const id = crypto.randomUUID()
    const now = new Date()

    // 这里可以保存到数据库，目前返回模拟数据
    return {
      id,
      ...policy,
      createdAt: now,
      updatedAt: now
    }
  }

  // 应用安全策略
  async applySecurityPolicy(versionId: string, _policyId: string): Promise<SecurityScanResult> {
    // 这里可以根据策略执行特定的安全检查
    // 目前返回基础扫描结果
    return this.performComprehensiveScan(versionId).then(results => results[0])
  }
}
